﻿using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public class WordInfo
{
    public int wordcount = 0;
    public int wordlevel = -1;
    public Hashtable subwordlist = new Hashtable();
}

public class SightWordInfo
{
    public int wordcount = 0;
    public int sightlevel = -1;
    public int dolchlevel = -1;
    public int category = -1;
    public int kwclevel = -1;
}

public partial class analyze_main : CWebBase
{
    CDatabase _db = new CDatabase();

    public string _text;
    public int _sentencecount = 0;
    public int _wordcount = 0;

    public Hashtable _wordlist = new Hashtable();
    public Hashtable _mainwordlist = new Hashtable();
    public ArrayList[] _sortwordlist = new ArrayList[9];
    public ArrayList[] _sortlist = new ArrayList[9];

    // sightwordlist 관련
    public Hashtable _sightmainwordlist = new Hashtable();
    public Hashtable _sightwordlist = new Hashtable();
    public ArrayList[] _sortsightwordlist = new ArrayList[5];
    public ArrayList[] _sortsightlist = new ArrayList[5];

    protected void Page_Load(object sender, EventArgs e)
    {
        _text = CheckNull(Request.Form["text"]);

        if (Request.Files.Get("uploadfile") != null && Request.Files.Get("uploadfile").FileName != "")
        {
            string filename = Request.Files.Get("uploadfile").FileName;
            filename = filename.Substring(filename.LastIndexOf("\\") + 1);

            string fileext = "";

            if (filename.IndexOf(".") > 0)
                fileext = filename.Substring(filename.LastIndexOf(".") + 1).ToLower();

            string filepath = Server.MapPath("/UploadFile/" + Guid.NewGuid().ToString() + "." + fileext);
            Request.Files.Get("uploadfile").SaveAs(filepath);

            if (fileext == "txt")
            {
                _text = ReadTextFile(filepath);
            }
            else if (fileext == "docx")
            {
                DocxToText dtt = new DocxToText(filepath);
                _text = dtt.ExtractText();
            }
            else
                ErrorBack("'" + fileext + "'은(는) 지원하지 않는 확장자입니다.");
        }

        if (_text != "")
        {
            _db.GetConnection();

            string contents = _text.ToLower();
            
            // 결합 단어 치환
            contents = contents.Replace("i’m", "i am");
            contents = contents.Replace("i’ll", "i will");
            contents = contents.Replace("we’ll", "we will");
            contents = contents.Replace("we’re", "we are");
            contents = contents.Replace("you’re", "you are");
            contents = contents.Replace("’s", " ");
            contents = contents.Replace("don’t", "do not");
            contents = contents.Replace("dosen’t", "does not");

            // 특수 문자 제거 (?, !의 경우에는 .으로 일괄 치환)
            contents = contents.Replace("\r", " ");
            contents = contents.Replace("\n", " ");
            contents = contents.Replace("\t", " ");
            contents = contents.Replace("\"", " ");
            contents = contents.Replace("\'", " ");
            contents = contents.Replace("@", " ");
            contents = contents.Replace("#", " ");
            contents = contents.Replace("$", " ");
            contents = contents.Replace("%", " ");
            contents = contents.Replace("^", " ");
            contents = contents.Replace("&", " ");
            contents = contents.Replace("*", " ");
            contents = contents.Replace("(", " ");
            contents = contents.Replace(")", " ");
            // contents = contents.Replace("-", " "); // JM120101: 하이픈으로 연결된 단어는 그대로 둠
            contents = contents.Replace("_", " ");
            contents = contents.Replace("+", " ");
            contents = contents.Replace("=", " ");
            contents = contents.Replace("{", " ");
            contents = contents.Replace("}", " ");
            contents = contents.Replace("[", " ");
            contents = contents.Replace("]", " ");
            contents = contents.Replace("|", " ");
            contents = contents.Replace("\\", " ");
            contents = contents.Replace(":", " ");
            contents = contents.Replace(";", " ");
            contents = contents.Replace(",", " ");
            contents = contents.Replace("/", " ");
            contents = contents.Replace("<", " ");
            contents = contents.Replace(">", " ");
            contents = contents.Replace("“", " ");
            contents = contents.Replace("”", " ");
            contents = contents.Replace("’", " ");
            contents = contents.Replace("?", ".");
            contents = contents.Replace("!", ".");
            
            // space 문자 하나로 합치기
            for (int i=0; i<1000; i++)
                contents = contents.Replace("  ", " ");

            // .으로 문장 구분
            string[] sentences = contents.Split('.');

            for (int i = 0; i < sentences.Length; i++)
            {
                string sentence = sentences[i].Trim();

                if (sentence != "")
                {
                    // space로 단어 구분
                    string[] words = sentence.Split(' ');

                    for (int j = 0; j < words.Length; j++)
                    {
                        string word = words[j].Trim().ToLower();

                        // 숫자로만 이루어졌을 경우 단어에서 제외
                        if (IsNumber(word))
                            continue;

                        // 1글자일 경우 단어에서 제외 (i, a는 단어로 취급)
                        if (word.Length == 1 && word != "i" && word != "a")
                            continue;

                        if (word != "")
                        {
                            // KWC Level 관련 처리

                            if (_mainwordlist[word] == null) // 지금까지 나왔던 mainword가 아니라면..
                            {
                                string mainword = word;

                                // 기본 어휘에 속해 있는 지 확인
                                string sql = "SELECT wordlevel FROM ANALYZE_WORD WHERE word='" + MRF(word) + "'";
                                string wordlevel = _db.GetQueryString(sql);

                                if (wordlevel == "") 
                                {
                                    // 변형 어휘에 속해 있는 지 확인
                                    sql = "SELECT word,wordlevel FROM ANALYZE_WORD_VARIATION WHERE wordvariation='" + MRF(word) + "'";

                                    SqlDataReader dr = _db.GetQueryResult(sql);

                                    if (dr.Read())
                                    {
                                        mainword = dr["word"].ToString().ToLower();
                                        wordlevel = dr["wordlevel"].ToString();
                                    }

                                    dr.Close();

                                    if (wordlevel == "")
                                        wordlevel = "-1";
                                
                                }

                                // _wordlist 구조:
                                //   - 각 mainword마다 하나의 WordInfo 가 할당됨
                                //   - 각 WordInfo에는 subwordlist 가 있고, 해당 subwordlist에는 현재의 mainword에 속하는 모든 정보가 들어감

                                WordInfo info = (WordInfo)_wordlist[mainword];
                                
                                if (info == null)
                                {
                                    info = new WordInfo();
                                    info.wordcount = 1;
                                    info.wordlevel = Convert.ToInt32(wordlevel);
                                }
                                else
                                    info.wordcount++;

                                WordInfo subinfo = new WordInfo();
                                subinfo.wordcount = 1;

                                info.subwordlist.Add(word, subinfo);

                                if ((WordInfo)_wordlist[mainword] == null)
                                    _wordlist.Add(mainword, info);

                                _mainwordlist.Add(word, mainword);  // word -> mainworld mapping table (word 자체가 mainword이더라도 본 테이블에 저장됨)
                            }
                            else
                            {
                                string mainword = _mainwordlist[word].ToString();

                                WordInfo info = (WordInfo)_wordlist[mainword];
                                info.wordcount++;

                                WordInfo subinfo = (WordInfo)info.subwordlist[word];
                                subinfo.wordcount++;
                            }

                            // Sight Level 관련 처리

                            if (_sightmainwordlist[word] == null)
                            {
                                string sightlevel = "";
                                string dolchlevel = "";
                                string category = "";

                                string mainword = word;

                                // 기본 어휘 체크
                                string sql = "SELECT word, sightlevel, dolchlevel, category FROM ANALYZE_SIGHT_WORD WHERE word='" + MRF(word) + "'";
                                SqlDataReader dr = _db.GetQueryResult(sql);

                                // 변형 어휘 체크하기
                                if (!dr.HasRows)
                                {
                                    dr.Close();
                                    sql = "SELECT word, sightlevel, dolchlevel, category FROM ANALYZE_SIGHT_WORD WHERE wordvariation='" + MRF(word) + "'";
                                    dr = _db.GetQueryResult(sql);
                                }

                                if (dr.HasRows)
                                {
                                    dr.Read();
                                    mainword = dr["word"].ToString();
                                    sightlevel = dr["sightlevel"].ToString();
                                    dolchlevel = dr["dolchlevel"].ToString();
                                    category = dr["category"].ToString();
                                }
                                else
                                {
                                    mainword = word;
                                    sightlevel = "-1";
                                    dolchlevel = "-1";
                                    category = "-1";
                                }

                                dr.Close();

                                SightWordInfo info = new SightWordInfo();
                                info.wordcount = 1;
                                info.sightlevel = Convert.ToInt32(sightlevel);
                                info.dolchlevel = Convert.ToInt32(dolchlevel);
                                info.category = Convert.ToInt32(category);
                                
                                string kwcmainword = _mainwordlist[word].ToString();
                                WordInfo kwcinfo = (WordInfo)_wordlist[kwcmainword];
                                info.kwclevel = Convert.ToInt32(kwcinfo.wordlevel);

                                if (_sightwordlist[mainword] == null)
                                    _sightwordlist.Add(mainword, info);

                                _sightmainwordlist.Add(word, mainword);
                            }
                            else
                            {
                                string mainword = _sightmainwordlist[word].ToString();
                                SightWordInfo info = (SightWordInfo)_sightwordlist[mainword];
                                info.wordcount++;
                            }

                            _wordcount++;
                        }
                    }

                    _sentencecount++;
                }
            }



            // 각 레벨별 단어 빈도수에 따라 Sort
            for (int i = 0; i < 9; i++)
            {
                _sortwordlist[i] = new ArrayList();
                _sortlist[i] = new ArrayList();
            }

            for (int i = 0; i < 9; i++)
            {
                int wordlevel = (i < 8) ? i : -1;

                IDictionaryEnumerator en = _wordlist.GetEnumerator();

                while (en.MoveNext())
                {
                    WordInfo info = (WordInfo)en.Value;

                    if (info.wordlevel == wordlevel)
                    {
                        _sortwordlist[i].Add(en.Key);
                        _sortlist[i].Add(info);
                    }
                }
            }

            _wordlist.Clear();

            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < _sortlist[i].Count - 1; j++)
                {
                    for (int k = j + 1; k < _sortlist[i].Count; k++)
                    {
                        WordInfo info1 = (WordInfo)_sortlist[i][j];
                        WordInfo info2 = (WordInfo)_sortlist[i][k];

                        if (info1.wordcount < info2.wordcount)
                        {
                            _sortlist[i][k] = info1;
                            _sortlist[i][j] = info2;

                            string word = _sortwordlist[i][k].ToString();
                            _sortwordlist[i][k] = _sortwordlist[i][j];
                            _sortwordlist[i][j] = word;
                        }
                    }
                }

                // wordlist도 update해줌
                for (int j = 0; j < _sortlist[i].Count; j++)
                {
                    _wordlist[_sortwordlist[i][j]] = _sortlist[i][j];
                }
            }

            // sight words도 sorting
            for (int i = 0; i < 5; i++)
            {
                _sortsightwordlist[i] = new ArrayList();
                _sortsightlist[i] = new ArrayList();
            }

            for (int i = 0; i < 5; i++)
            {
                int sightlevel, category;

                switch (i)
                {
                    case 0: sightlevel = 1; category = 1; break;
                    case 1: sightlevel = 1; category = 2; break;
                    case 2: sightlevel = 2; category = 1; break;
                    case 3: sightlevel = 2; category = 2; break;
                    default: sightlevel = -1; category = -1; break; // case 4
                }

                IDictionaryEnumerator en = _sightwordlist.GetEnumerator();

                while (en.MoveNext())
                {
                    SightWordInfo info = (SightWordInfo)en.Value;

                    if (info.sightlevel == sightlevel && info.category == category)
                    {
                        _sortsightwordlist[i].Add(en.Key);
                        _sortsightlist[i].Add(info);
                    }
                }
            }

            _sightwordlist.Clear();

            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < _sortsightlist[i].Count - 1; j++)
                {
                    for (int k = j + 1; k < _sortsightlist[i].Count; k++)
                    {
                        SightWordInfo info1 = (SightWordInfo)_sortsightlist[i][j];
                        SightWordInfo info2 = (SightWordInfo)_sortsightlist[i][k];

                        if (info1.wordcount < info2.wordcount)
                        {
                            _sortsightlist[i][k] = info1;
                            _sortsightlist[i][j] = info2;

                            string word = _sortsightwordlist[i][k].ToString();
                            _sortsightwordlist[i][k] = _sortsightwordlist[i][j];
                            _sortsightwordlist[i][j] = word;
                        }
                    }
                }

                // sightwordlist도 update해줌
                for (int j = 0; j < _sortsightlist[i].Count; j++)
                {
                    _sightwordlist[_sortsightwordlist[i][j]] = _sortsightlist[i][j];
                }
            }

        }
    }

    public bool IsNumber(string pString)
    {
        if (pString == null || pString == "")
            return false;

        string number = "0123456789";

        for (int i = 0; i < pString.Length; i++)
        {
            if (number.IndexOf(pString.Substring(i, 1)) == -1)
            {
                return false;
            }
        }

        return true;
    }

    public int GetWordLevelCount(int wordlevel)
    {
        int wordcount = 0;

        IDictionaryEnumerator en = _wordlist.GetEnumerator();

        while (en.MoveNext())
        {
            WordInfo info = (WordInfo)en.Value;

            if (info.wordlevel == wordlevel || wordlevel == -2)
                wordcount++;
        }

        return wordcount;
    }

    public double GetWordLevelPercent(int wordlevel)
    {
        int wordcount = 0;
        int totalwordcount = 0;

        IDictionaryEnumerator en = _wordlist.GetEnumerator();

        while (en.MoveNext())
        {
            WordInfo info = (WordInfo)en.Value;

            if (info.wordlevel == wordlevel || wordlevel == -2)
                wordcount++;

            totalwordcount++;
        }

        if (totalwordcount == 0)
            return 0;

        int npercent = (totalwordcount > 0) ? wordcount * 10000 / totalwordcount : 0;

        return (double)npercent / 100.0;
    }

    public int GetWordLevelCountDuplicate(int wordlevel)
    {
        int wordcount = 0;

        IDictionaryEnumerator en = _wordlist.GetEnumerator();

        while (en.MoveNext())
        {
            WordInfo info = (WordInfo)en.Value;

            if (info.wordlevel == wordlevel || wordlevel == -2)
                wordcount += info.wordcount;
        }

        return wordcount;
    }

    public double GetWordLevelPercentDuplicate(int wordlevel)
    {
        int wordcount = 0;
        int totalwordcount = 0;

        IDictionaryEnumerator en = _wordlist.GetEnumerator();

        while (en.MoveNext())
        {
            WordInfo info = (WordInfo)en.Value;

            if (info.wordlevel == wordlevel || wordlevel == -2)
                wordcount += info.wordcount;

            totalwordcount += info.wordcount;
        }

        if (totalwordcount == 0)
            return 0;

        int npercent = (totalwordcount > 0) ? wordcount * 10000 / totalwordcount : 0;

        return (double)npercent / 100.0;
    }

    public int GetSightLevelCount(int sightlevel, int category)
    {
        int wordcount = 0;

        IDictionaryEnumerator en = _sightwordlist.GetEnumerator();

        while (en.MoveNext())
        {
            SightWordInfo info = (SightWordInfo)en.Value;

            if ((info.sightlevel == sightlevel && info.category == category) || sightlevel == -2)
                wordcount++;
       }
        return wordcount;
    }

    public double GetSightLevelPercent(int sightlevel, int category)
    {
        int wordcount = 0;
        int totalwordcount = 0;

        IDictionaryEnumerator en = _sightwordlist.GetEnumerator();

        while (en.MoveNext())
        {
            SightWordInfo info = (SightWordInfo)en.Value;

            if ((info.sightlevel == sightlevel && info.category == category) || sightlevel == -2)
                wordcount++;

            totalwordcount++;
        }

        if (totalwordcount == 0)
            return 0;

        int npercent = (totalwordcount > 0) ? wordcount * 10000 / totalwordcount : 0;

        return (double)npercent/100.0;
    }

    public int GetSightLevelCountDuplicate(int sightlevel, int category)
    {
        int wordcount = 0;

        IDictionaryEnumerator en = _sightwordlist.GetEnumerator();

        while (en.MoveNext())
        {
            SightWordInfo info = (SightWordInfo)en.Value;

            if ((info.sightlevel == sightlevel && info.category == category) || sightlevel == -2)
                wordcount += info.wordcount;
        }
        return wordcount;
    }

    public double GetSightLevelPercentDuplicate(int sightlevel, int category)
    {
        int wordcount = 0;
        int totalwordcount = 0;

        IDictionaryEnumerator en = _sightwordlist.GetEnumerator();

        while (en.MoveNext())
        {
            SightWordInfo info = (SightWordInfo)en.Value;

            if ((info.sightlevel == sightlevel && info.category == category) || sightlevel == -2)
                wordcount += info.wordcount;

            totalwordcount += info.wordcount;
        }

        if (totalwordcount == 0)
            return 0;

        int npercent = (totalwordcount > 0) ? wordcount * 10000 / totalwordcount : 0;

        return (double)npercent / 100.0;
    }

    
    public double GetRepetitionPercent()
    {
        int npercent = (_wordcount > 0) ? (_wordcount - _wordlist.Count) * 10000 / _wordcount : 0;

        return (double)npercent / 100.0;
    }

    public string GetWordDetail(int wordlevel)
    {
        if (GetWordLevelCount(wordlevel) == 0)
            return "* 단어가 없습니다.";

        string detail = "<ul>";

        IDictionaryEnumerator en = _wordlist.GetEnumerator();

        while (en.MoveNext())
        {
            WordInfo info = (WordInfo)en.Value;

            if (info.wordlevel == wordlevel)
            {
                detail += "<li>";
                detail += en.Key.ToString() + "(" + info.wordcount + ")<br> 변형형 : ";

                IDictionaryEnumerator suben = info.subwordlist.GetEnumerator();

                int count = 0;

                while (suben.MoveNext())
                {
                    WordInfo subinfo = (WordInfo)suben.Value;

                    if (count != 0)
                        detail += ", ";

                    detail += suben.Key.ToString() + "(" + subinfo.wordcount + ")";

                    count++;
                }

                detail += "</li>";
            }
        }

        detail += "</ul>";

        return detail;
    }

    public float GetSentenceWordCount()
    {
        if (_sentencecount == 0)
            return 0;

        int wordcount = _wordcount * 100 / _sentencecount;

        return (float)wordcount / 100.0f;
    }

    protected void Page_Unload(object sender, EventArgs e)
    {
        if (_db != null)
            _db.ReleaseConnection();
    }
}
